﻿using Common.Infrastructure.Service;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Common.AspNetCore
{
    public class ApiAuthorizeAttribute : TypeFilterAttribute
    { 
        private readonly bool ignoreFilter; 

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="ignore">是否忽略过滤。默认为false</param>
        public ApiAuthorizeAttribute(bool ignore = false) : base(typeof(ApiAuthorizeFilter))
        {
            this.ignoreFilter = ignore;
            this.Arguments = new object[] { ignore };
        }
         
        /// <summary>
        /// 获取是否忽略过滤？
        /// </summary>
        public bool IgnoreFilter => ignoreFilter;
          
        /// <summary>
        /// 管理员授权过滤器
        /// </summary>
        private class ApiAuthorizeFilter : IAuthorizationFilter
        { 
            private readonly bool ignoreFilter; 

            public ApiAuthorizeFilter(bool ignoreFilter)
            {
                this.ignoreFilter = ignoreFilter; 
            }

            public void OnAuthorization(AuthorizationFilterContext filterContext)
            {
                if (filterContext == null)
                {
                    throw new ArgumentNullException(nameof(filterContext));
                }

                var actionFilter = filterContext.ActionDescriptor.FilterDescriptors
                    .Where(filterDescriptor => filterDescriptor.Scope == FilterScope.Action)
                    .Select(filterDescriptor => filterDescriptor.Filter).OfType<ApiAuthorizeAttribute>().FirstOrDefault();

                if (actionFilter?.IgnoreFilter ?? ignoreFilter)
                {
                    return;
                }

                if (filterContext.Filters.Any(filter => filter is ApiAuthorizeFilter))
                {
                    IUserTokenService tokenService = null;
                    try
                    {
                        if (filterContext.HttpContext != null && filterContext.HttpContext.RequestServices != null)
                        {
                            tokenService = (IUserTokenService)filterContext.HttpContext.RequestServices.GetService(typeof(IUserTokenService));
                        }
                    }
                    catch
                    {
                    }

                    var token = tokenService?.GetUserToken();
                    if (token != null && string.IsNullOrEmpty(token.Id))
                    {
                        filterContext.Result = new StatusCodeResult(401);
                    }
                }
            }
        } 
    }
}
